<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>DALI场景配置生成器</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#165DFF',
                        secondary: '#36CFC9',
                        neutral: '#86909C',
                        light: '#F2F3F5',
                        dark: '#1D2129'
                    },
                    fontFamily: { inter: ['Inter', 'system-ui', 'sans-serif'] },
                    boxShadow: { card: '0 4px 12px rgba(0,0,0,.08)', hover: '0 8px 24px rgba(0,0,0,.12)' }
                }
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .checkbox-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(40px, 1fr)); gap: 5px; }
            .checkbox-item { position: relative; display: flex; align-items: center; justify-content: center; padding: 6px 10px; min-width: 36px; min-height: 36px; border: 1px solid #e5e7eb; border-radius: 6px; cursor: pointer; }
            .checkbox-item.checked { background: #165DFF; color: #fff; border-color: #165DFF; }
            .checkbox-item input { position: absolute; opacity: 0; width: 0; height: 0; }
            .checkbox-item label { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; cursor: pointer; }
            .checkbox-item-large { min-width: 40px; min-height: 40px; padding: 8px 12px; }
        }
    </style>
</head>
<body class="font-inter bg-light min-h-screen">
<header class="bg-white shadow-md sticky top-0 z-50">
    <div class="container mx-auto px-4 py-4 flex justify-between items-center">
        <div class="flex items-center space-x-2">
            <i class="fa fa-file-code-o text-primary text-2xl"></i>
            <h1 class="text-xl font-bold text-dark">DALI场景配置生成器</h1>
        </div>
        <button id="theme-toggle" class="p-2 rounded-full hover:bg-light transition-custom"><i class="fa fa-moon-o text-neutral"></i></button>
    </div>
</header>

<main class="container mx-auto px-4 py-8">
    <div class="bg-info/10 border border-info/30 rounded-xl p-4 mb-6 text-sm text-dark/80 space-y-2">
        <p>1. 输入MAC地址（无冒号）与区域</p>
        <p>2. 选择场景模式（0-15），自定义场景可双击改名</p>
        <p>3. 勾选分组地址后点击“批量生成YAML”</p>
        <p>4. 先在configuration.yaml里面添加一行代码：mqtt: </p>    
        <p>5. 把生成的yaml复制到mqtt:后面，保存</p>
        <p>6. 重启Home Assistant</p>
    </div>

    <div class="grid grid-cols-1 lg:grid-cols-12 gap-8">
        <!-- 左侧表单 -->
        <div class="lg:col-span-5 bg-white rounded-xl shadow-card p-6">
            <h2 class="text-lg font-semibold text-dark mb-6"><i class="fa fa-pencil-square-o text-primary mr-2"></i>批量场景配置</h2>
            <form id="dali-form" class="space-y-5">
                <div>
                    <label class="block text-sm font-medium text-neutral mb-1">MAC地址 <span class="text-red-500">*</span></label>
                    <input type="text" id="mac-address" value="c049ef3f22d4" required class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary transition-custom">
                </div>
                <div>
                    <label class="block text-sm font-medium text-neutral mb-1">区域 <span class="text-red-500">*</span></label>
                    <input type="text" id="area-input" required class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary transition-custom" placeholder="如：一楼客厅">
                </div>
                <div>
                    <label class="block text-sm font-medium text-neutral mb-1">场景模式 <span class="text-red-500">*</span></label>
                    <input type="text" id="scene-name-prefix" readonly required class="w-full px-3 py-2 border border-gray-300 rounded-lg bg-gray-50 cursor-not-allowed" placeholder="请选择场景模式">
                    <input type="hidden" id="selected-scene-number">
                    <div class="mt-2 grid grid-cols-3 gap-2">
                        <!-- 0-12 固定场景 -->
                        <button type="button" class="prefix-option py-1 text-sm border border-gray-300 rounded-md hover:bg-gray-50" data-value="全开" data-scene="0">全开(0)</button>
                        <button type="button" class="prefix-option py-1 text-sm border border-gray-300 rounded-md hover:bg-gray-50" data-value="会客" data-scene="1">会客(1)</button>
                        <button type="button" class="prefix-option py-1 text-sm border border-gray-300 rounded-md hover:bg-gray-50" data-value="明亮" data-scene="2">明亮(2)</button>
                        <button type="button" class="prefix-option py-1 text-sm border border-gray-300 rounded-md hover:bg-gray-50" data-value="清洁" data-scene="3">清洁(3)</button>
                        <button type="button" class="prefix-option py-1 text-sm border border-gray-300 rounded-md hover:bg-gray-50" data-value="全关" data-scene="4">全关(4)</button>
                        <button type="button" class="prefix-option py-1 text-sm border border-gray-300 rounded-md hover:bg-gray-50" data-value="离家" data-scene="5">离家(5)</button>
                        <button type="button" class="prefix-option py-1 text-sm border border-gray-300 rounded-md hover:bg-gray-50" data-value="回屋" data-scene="6">回屋(6)</button>
                        <button type="button" class="prefix-option py-1 text-sm border border-gray-300 rounded-md hover:bg-gray-50" data-value="休闲" data-scene="7">休闲(7)</button>
                        <button type="button" class="prefix-option py-1 text-sm border border-gray-300 rounded-md hover:bg-gray-50" data-value="娱乐" data-scene="8">娱乐(8)</button>
                        <button type="button" class="prefix-option py-1 text-sm border border-gray-300 rounded-md hover:bg-gray-50" data-value="温馨" data-scene="9">温馨(9)</button>
                        <button type="button" class="prefix-option py-1 text-sm border border-gray-300 rounded-md hover:bg-gray-50" data-value="睡眠" data-scene="10">睡眠(10)</button>
                        <button type="button" class="prefix-option py-1 text-sm border border-gray-300 rounded-md hover:bg-gray-50" data-value="夜间" data-scene="11">夜间(11)</button>
                        <button type="button" class="prefix-option py-1 text-sm border border-gray-300 rounded-md hover:bg-gray-50" data-value="起夜" data-scene="12">起夜(12)</button>
                        <!-- 13-15 自定义场景 -->
                        <button type="button" class="prefix-option py-1 text-sm border border-gray-300 rounded-md hover:bg-gray-50 custom-scene" data-value="自定义1" data-scene="13">自定义1(13)</button>
                        <button type="button" class="prefix-option py-1 text-sm border border-gray-300 rounded-md hover:bg-gray-50 custom-scene" data-value="自定义2" data-scene="14">自定义2(14)</button>
                        <button type="button" class="prefix-option py-1 text-sm border border-gray-300 rounded-md hover:bg-gray-50 custom-scene" data-value="自定义3" data-scene="15">自定义3(15)</button>
                    </div>
                </div>
                <div>
                    <label class="block text-sm font-medium text-neutral mb-2">分组地址选择 (0-79) <span class="text-red-500">*</span></label>
                    <div id="group-checkboxes" class="checkbox-grid mb-2"></div>
                    <div class="flex gap-2">
                        <button type="button" id="select-all-groups" class="text-xs bg-primary/10 text-primary px-3 py-1 rounded-md hover:bg-primary/20">全选</button>
                        <button type="button" id="deselect-all-groups" class="text-xs bg-light text-neutral px-3 py-1 rounded-md hover:bg-gray-200">全不选</button>
                        <button type="button" id="select-range-groups" class="text-xs bg-secondary/10 text-secondary px-3 py-1 rounded-md hover:bg-secondary/20">选择范围</button>
                    </div>
                </div>
                <button type="submit" class="w-full bg-primary hover:bg-primary/90 text-white font-medium py-2 px-4 rounded-lg transition-custom"><i class="fa fa-magic mr-2"></i>批量生成YAML</button>
            </form>
        </div>

        <!-- 右侧结果 -->
        <div class="lg:col-span-7 bg-white rounded-xl shadow-card p-6">
            <div class="flex justify-between items-center mb-6">
                <h2 class="text-lg font-semibold text-dark"><i class="fa fa-file-text-o text-primary mr-2"></i>批量生成结果</h2>
                <div class="flex gap-2">
                    <button id="copy-btn" class="p-2 text-neutral hover:text-primary rounded-lg hover:bg-light" title="复制代码"><i class="fa fa-copy"></i></button>
                    <button id="download-btn" class="p-2 text-neutral hover:text-primary rounded-lg hover:bg-light" title="下载文件"><i class="fa fa-download"></i></button>
                </div>
            </div>
            <div class="bg-light/50 p-3 rounded-lg mb-4 text-sm flex justify-between">
                <span>已选择 <span id="selected-count" class="font-medium text-primary">0</span> 个分组地址</span>
                <span>预计生成 <span id="total-configs-count" class="font-medium text-primary">0</span> 个配置</span>
            </div>
            <div class="relative">
                <pre id="yaml-output" class="bg-dark/5 p-4 rounded-lg overflow-x-auto text-sm font-mono h-[400px] border border-gray-200"></pre>
                <div id="copy-notice" class="absolute top-2 right-2 bg-green-500 text-white text-xs px-2 py-1 rounded opacity-0 transition-opacity duration-300"><i class="fa fa-check mr-1"></i>已复制</div>
            </div>
        </div>
    </div>
</main>

<!-- 范围选择弹窗 -->
<div id="range-modal" class="fixed inset-0 bg-black/50 items-center justify-center z-50 hidden">
    <div class="bg-white rounded-xl p-6 w-full max-w-md">
        <h3 class="text-lg font-semibold text-dark mb-4">选择分组地址范围</h3>
        <div class="space-y-4">
            <div>
                <label class="block text-sm font-medium text-neutral mb-1">起始地址</label>
                <input type="number" id="start-range" min="0" max="79" value="0" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary">
            </div>
            <div>
                <label class="block text-sm font-medium text-neutral mb-1">结束地址</label>
                <input type="number" id="end-range" min="0" max="79" value="79" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary">
            </div>
            <div class="flex gap-2 mt-6">
                <button id="apply-range" class="flex-1 bg-primary hover:bg-primary/90 text-white font-medium py-2 px-4 rounded-lg">应用</button>
                <button id="cancel-range" class="flex-1 bg-light hover:bg-gray-200 text-dark font-medium py-2 px-4 rounded-lg">取消</button>
            </div>
        </div>
    </div>
</div>

<footer class="bg-white shadow-inner mt-12 py-6 text-center text-sm text-neutral">
    <p>DALI场景配置生成器 &copy; 2025</p>
    <p class="mt-1">轻量级本地网页工具，无需服务器，安全便捷</p>
</footer>

<script>
/* ========================== 初始化 ========================== */
document.addEventListener('DOMContentLoaded', () => {
    generateGroupCheckboxes();
    updateCounters();
    initHandlers();
});

/* ------------------- 生成分组地址复选框 ------------------- */
function generateGroupCheckboxes() {
    const box = document.getElementById('group-checkboxes');
    for (let i = 0; i < 80; i++) {
        if (i === 64) {
            const sep = document.createElement('div');
            sep.className = 'w-full py-2 text-center text-xs text-neutral font-bold';
            sep.textContent = '以下为分组';
            box.appendChild(sep);
        }
        const div = document.createElement('div');
        div.className = i >= 64 && i <= 79 ? 'checkbox-item checkbox-item-large' : 'checkbox-item';
        const display = i >= 64 && i <= 79 ? `${i}(${i - 64})` : i;
        div.innerHTML = `<input type="checkbox" id="group-${i}" name="group-addresses" value="${i}"><label for="group-${i}">${display}</label>`;
        box.appendChild(div);
    }
}

/* ------------------- 事件委托汇总 ------------------- */
function initHandlers() {
    /* 场景模式按钮 */
    document.querySelectorAll('.prefix-option').forEach(btn => {
        btn.addEventListener('click', function () {
            document.getElementById('scene-name-prefix').value = this.dataset.value;
            document.getElementById('selected-scene-number').value = this.dataset.scene;
            document.querySelectorAll('.prefix-option').forEach(b => b.classList.remove('bg-primary/10', 'text-primary', 'border-primary'));
            this.classList.add('bg-primary/10', 'text-primary', 'border-primary');
            updateCounters();
        });
    });
    /* 自定义场景双击改名 */
    document.querySelectorAll('.custom-scene').forEach(btn => {
        btn.addEventListener('dblclick', function () {
            const nv = prompt('请输入自定义场景名称：', this.dataset.value);
            if (nv && nv.trim()) {
                this.dataset.value = nv.trim();
                this.textContent = `${nv.trim()}(${this.dataset.scene})`;
            }
        });
    });
    /* 分组复选框点击 */
    document.getElementById('group-checkboxes').addEventListener('click', e => {
        const item = e.target.closest('.checkbox-item');
        if (!item) return;
        const cb = item.querySelector('input');
        cb.checked = !cb.checked;
        item.classList.toggle('checked', cb.checked);
        updateCounters();
    });
    /* 全选 / 全不选 / 范围选择 */
    document.getElementById('select-all-groups').addEventListener('click', () => checkAll(true));
    document.getElementById('deselect-all-groups').addEventListener('click', () => checkAll(false));
    document.getElementById('select-range-groups').addEventListener('click', () => {
        document.getElementById('range-modal').classList.remove('hidden');
    });
    document.getElementById('cancel-range').addEventListener('click', () => {
        document.getElementById('range-modal').classList.add('hidden');
    });
    document.getElementById('apply-range').addEventListener('click', applyRange);
    /* 点击遮罩关闭弹窗 */
    document.getElementById('range-modal').addEventListener('click', e => {
        if (e.target === document.getElementById('range-modal')) document.getElementById('range-modal').classList.add('hidden');
    });
    /* 表单提交 */
    document.getElementById('dali-form').addEventListener('submit', e => {
        e.preventDefault();
        generateBatchYaml();
    });
    /* 复制 & 下载 */
    document.getElementById('copy-btn').addEventListener('click', copyResult);
    document.getElementById('download-btn').addEventListener('click', downloadResult);
}

/* ------------------- 勾选控制 ------------------- */
function checkAll(checked) {
    document.querySelectorAll('input[name="group-addresses"]').forEach(cb => {
        cb.checked = checked;
        cb.closest('.checkbox-item').classList.toggle('checked', checked);
    });
    updateCounters();
}
function applyRange() {
    const s = parseInt(document.getElementById('start-range').value, 10);
    const e = parseInt(document.getElementById('end-range').value, 10);
    if (isNaN(s) || isNaN(e) || s < 0 || e > 79 || s > e) return alert('请输入有效范围（0-79）');
    checkAll(false);
    for (let i = s; i <= e; i++) {
        const cb = document.getElementById(`group-${i}`);
        cb.checked = true;
        cb.closest('.checkbox-item').classList.add('checked');
    }
    updateCounters();
    document.getElementById('range-modal').classList.add('hidden');
}
function updateCounters() {
    const sel = document.querySelectorAll('input[name="group-addresses"]:checked').length;
    const hasScene = !!document.getElementById('scene-name-prefix').value.trim();
    document.getElementById('selected-count').textContent = sel;
    document.getElementById('total-configs-count').textContent = hasScene ? sel : 0;
}

/* ------------------- YAML 生成（已去掉 mqtt:，unique_id 带分组地址与场景号） ------------------- */
function generateBatchYaml() {
    const mac = document.getElementById('mac-address').value.trim();
    const area = document.getElementById('area-input').value.trim();
    const prefix = document.getElementById('scene-name-prefix').value.trim();
    const sceneNum = parseInt(document.getElementById('selected-scene-number').value, 10);
    const groups = Array.from(document.querySelectorAll('input[name="group-addresses"]:checked'))
                        .map(cb => parseInt(cb.value, 10))
                        .sort((a, b) => a - b);

    if (!mac) return alert('请输入MAC地址');
    if (!area) return alert('请输入区域');
    if (!prefix || isNaN(sceneNum)) return alert('请选择场景模式');
    if (groups.length === 0) return alert('请至少选择一个分组地址');

    let yaml = '';
    groups.forEach((g, idx) => {
        const sceneName = `${area}${sceneNum}${prefix}`;
        const uid = `uolo-cj-${g}-${sceneNum}`;   // ← 关键改动
        const topic = `d2m_${mac}/${g}/set`;
        if (idx !== 0) yaml += '\n';
        yaml += `  - scene:\n`;
        yaml += `      name: ${sceneName}\n`;
        yaml += `      unique_id: ${uid}\n`;
        yaml += `      command_topic: ${topic}\n`;
        yaml += `      payload_on: "{\\"scene\\":${sceneNum}}"`;
    });

    document.getElementById('yaml-output').textContent = yaml;
}

/* ------------------- 复制 & 下载 ------------------- */
function copyResult() {
    const y = document.getElementById('yaml-output').textContent;
    if (!y) return alert('暂无内容可复制');
    navigator.clipboard.writeText(y).then(() => showCopyNotice(), () => fallbackCopy(y));
}
function fallbackCopy(text) {
    const ta = document.createElement('textarea');
    ta.value = text; ta.style.position = 'fixed'; ta.style.opacity = 0;
    document.body.appendChild(ta); ta.select(); document.execCommand('copy');
    document.body.removeChild(ta); showCopyNotice();
}
function showCopyNotice() {
    const tip = document.getElementById('copy-notice');
    tip.style.opacity = '1'; setTimeout(() => tip.style.opacity = '0', 2000);
}
function downloadResult() {
    const y = document.getElementById('yaml-output').textContent;
    if (!y) return alert('暂无内容可下载');
    const blob = new Blob([y], { type: 'text/yaml;charset=utf-8' });
    const url = URL.createObjectURL(blob);
    const a = Object.assign(document.createElement('a'), { href: url, download: 'dali_scenes.yaml' });
    document.body.appendChild(a); a.click(); document.body.removeChild(a);
    URL.revokeObjectURL(url);
}

/* ------------------- 主题切换（占位） ------------------- */
document.getElementById('theme-toggle').addEventListener('click', () => {
    alert('暗色主题功能开发中');
});
</script>
</body>
</html>